home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / ICMP.C < prev    next >
Text File  |  1990-06-06  |  4KB  |  159 lines

  1. /* Internet Control Message Protocol */
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "internet.h"
  5. #include "timer.h"
  6. #include "iface.h"
  7. #include "ip.h"
  8. #include "icmp.h"
  9.  
  10. struct icmp_errors icmp_errors;
  11. struct icmp_stats icmp_stats;
  12.  
  13. /* Process an incoming ICMP packet */
  14. void
  15. icmp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  16. struct mbuf *bp;    /* Pointer to ICMP message */
  17. char protocol;        /* Should always be ICMP_PTCL */
  18. int32 source;        /* Sender of ICMP message */
  19. int32 dest;        /* Us */
  20. char tos;        /* Type of Service */
  21. int16 length;        /* Length of ICMP message */
  22. char rxbroadcast;
  23. {
  24.     struct mbuf *htonicmp(),*tbp;
  25.     struct icmp icmp;    /* ICMP header */
  26.     struct ip ip;        /* Offending datagram header */
  27.     int16 type;        /* Type of ICMP message */
  28.  
  29.     if(rxbroadcast){
  30.         /* Broadcast ICMP packets are to be IGNORED !! */
  31.         icmp_errors.bdcsts++;
  32.         free_p(bp);
  33.         return;
  34.     }
  35.     if(cksum(NULLHEADER,bp,length) != 0){
  36.         /* Bad ICMP checksum; discard */
  37.         icmp_errors.checksum++;
  38.         free_p(bp);
  39.         return;
  40.     }
  41.     ntohicmp(&icmp,&bp);
  42.  
  43.     /* Process the message. Some messages are passed up to the protocol
  44.      * module for handling, others are handled here.
  45.      */
  46.     type = icmp.type;
  47.     if(type < ICMP_TYPES)
  48.         icmp_stats.input[type]++;
  49.  
  50.     switch(uchar(type)){
  51.     case TIME_EXCEED:    /* Time-to-live Exceeded */
  52.     case DEST_UNREACH:    /* Destination Unreachable */
  53.     case QUENCH:        /* Source Quench */
  54.         ntohip(&ip,&bp);    /* Extract offending IP header */
  55.         switch(uchar(ip.protocol)){
  56.         case TCP_PTCL:
  57.             tcp_icmp(ip.source,ip.dest,icmp.type,icmp.code,&bp);
  58.             break;
  59.         }
  60.         break;
  61.     case ECHO_REQ:        /* Echo Request */
  62.         /* Change type to ECHO_REPLY, recompute checksum,
  63.          * and return datagram.
  64.          */
  65.         icmp.type = ECHO_REPLY;
  66.         if((tbp = htonicmp(&icmp,bp)) == NULLBUF){
  67.             free_p(bp);
  68.             return;
  69.         }
  70.         icmp_stats.output[ECHO_REPLY]++;
  71.         ip_send(dest,source,ICMP_PTCL,tos,0,tbp,length,0,0);
  72.         return;
  73.     case REDIRECT:        /* Redirect */
  74.     case PARAM_PROB:    /* Parameter Problem */
  75.         break;
  76.     case ECHO_REPLY:    /* Echo Reply */
  77.         echo_proc(source,dest,&icmp);
  78.         break;
  79.     case TIMESTAMP:        /* Timestamp */
  80.     case TIME_REPLY:    /* Timestamp Reply */
  81.     case INFO_RQST:        /* Information Request */
  82.     case INFO_REPLY:    /* Information Reply */
  83.         break;
  84.     }
  85.     free_p(bp);
  86. }
  87. /* Return an ICMP response to the sender of a datagram.
  88.  * Unlike most routines, the callER frees the mbuf.
  89.  */
  90. int
  91. icmp_output(ip,data,type,code,args)
  92. struct ip *ip;        /* Header of offending datagram */
  93. struct mbuf *data;    /* Data portion of datagram */
  94. char type,code;        /* Codes to send */
  95. union icmp_args *args;
  96. {
  97.     struct mbuf *htonicmp();
  98.     struct mbuf *htonip();
  99.     struct mbuf *bp;
  100.     struct icmp icmp;    /* ICMP protocol header */
  101.     int16 dlen;        /* Length of data portion of offending pkt */
  102.     int16 length;        /* Total length of reply */
  103.     extern int32 ip_addr;    /* Our IP address */
  104.  
  105.     if(ip == NULLIP)
  106.         return -1;
  107.     if(type < ICMP_TYPES)
  108.         icmp_stats.output[type]++;
  109.  
  110.     if(uchar(ip->protocol) == ICMP_PTCL){
  111.         /* Never send an ICMP message about another ICMP message */
  112.         icmp_errors.noloop++;
  113.         return -1;
  114.     }
  115.     /* Compute amount of original datagram to return.
  116.      * We return the original IP header, and up to 8 bytes past that.
  117.      */
  118.     dlen = min(8,len_mbuf(data));
  119.     length = dlen + ICMPLEN + IPLEN + ip->optlen;
  120.     /* Take excerpt from data portion */
  121.     if(data != NULLBUF && (bp = copy_p(data,dlen)) == NULLBUF)
  122.         return -1;    /* The caller will free data */
  123.  
  124.     /* Recreate and tack on offending IP header */
  125.     if((data = htonip(ip,bp)) == NULLBUF){
  126.         free_p(bp);
  127.         return -1;
  128.     }
  129.     icmp.type = type;
  130.     icmp.code = code;
  131.     switch(uchar(icmp.type)){
  132.     case PARAM_PROB:
  133.         icmp.args.pointer = args->pointer;
  134.         break;
  135.     case REDIRECT:
  136.         icmp.args.address = args->address;
  137.         break;
  138.     case ECHO_REQ:
  139.     case ECHO_REPLY:
  140.     case INFO_RQST:
  141.     case INFO_REPLY:
  142.     case TIMESTAMP:
  143.     case TIME_REPLY:
  144.         icmp.args.echo.id = args->echo.id;
  145.         icmp.args.echo.seq = args->echo.seq;
  146.         break;
  147.     default:
  148.         icmp.args.unused = 0;
  149.         break;
  150.     }
  151.     /* Now stick on the ICMP header */
  152.     if((bp = htonicmp(&icmp,data)) == NULLBUF){
  153.         free_p(data);
  154.         return -1;
  155.     }
  156.     return ip_send(ip_addr,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
  157. }
  158.  
  159. ə